<?php

namespace App\Models;

use Exception;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Support\Facades\Cache;

/**
 * 用户违规情况
 */
class UserViolate extends BaseModel
{
  use HasFactory;


  //  public $incrementing = false;//主键不自增

  const CREATED_AT = 'create_time';
  const UPDATED_AT = 'change_time';


  protected $table = 'user_violate';

  /**
   * 清空违规次数
   * @param user_id 用户id
   * @param violate_field  all 全部清空  其余，根据违规返回字段清空
   */
  public function clearViolate($user_id, $violate_field)
  {
    if ($user_id) {
      $user_id_all[] = $user_id; //转换为数组操作
      $user_violate_user_id = $this->where('user_id', $user_id)->pluck('user_id')->toArray();
    } else {
      //批量操作所有的用户
      $user_id_all = UserInfo::pluck('id')->toArray();
      //查询已有的用户id
      $user_violate_user_id = $this->pluck('user_id')->toArray();
    }
    $change_user_id = array_intersect($user_id_all, $user_violate_user_id); //取交集，为修改，另外为新增

    $data = [];
    //清空所有
    foreach ($violate_field as $key => $val) {
      $data[$val . '_violate_num'] = 0;
      $data[$val . '_violate_clear_time'] = date('Y-m-d H:i:s');
    }

    $data['change_time'] = date('Y-m-d H:i:s');
    if ($change_user_id) {
      $this->whereIn('user_id', $change_user_id)->update($data);
    }
    if (count($user_violate_user_id) != count($user_id_all)) {
      $data['create_time'] = date('Y-m-d H:i:s');
      $this->whereIn('user_id', $user_id_all)->whereNotIn('user_id', $user_violate_user_id)->insert($data);
    }

    return true;
  }

  /**
   * 重置违规次数(不是清空，主要作用是为了查询违规)
   * @param user_id 用户id
   * @param violate_config_field  all 全部清空  其余，根据违规返回字段清空
   */
  public function resetViolate($user_id, $violate_config_field)
  {
    $cache_key = 'violate_number';
    $cache = Cache::get($cache_key);
    if ($cache) {
      return true;
    }

    if ($user_id) {
      $user_id_all[] = $user_id; //转换为数组操作
    } else {
      //批量操作所有的用户
      $user_id_all = UserInfo::orderBy('id')->pluck('id')->toArray();
    }
    foreach ($user_id_all as $key => $val) {
      $data = [];
      //清空所有
      foreach ($violate_config_field as $k => $v) {
        $data[$v . '_violate_num'] = $this->getViolateNumberOrUserId($val, $v);
      }

      $this->chanegViolate($val, $data);
    }
    $cache = Cache::put($cache_key, 1, 60 * 30); //半个小时重置一次
    return true;
  }

  /**
   * 新增一条违规记录
   */
  public function addViolate($user_id, $data = [])
  {
    $res = new self();
    $data['user_id'] = $user_id;
    $res->add($data);
    return $res->id;
  }
  /**
   * 新增一条违规记录
   */
  public function chanegViolate($user_id, $data)
  {
    $res = $this->where('user_id', $user_id)->first();
    if (empty($res)) {
      //新增违规记录
      $id = $this->addViolate($user_id, $data);
      return $id;
    }
    foreach ($data as $key => $val) {
      $res->$key = $val;
    }
    $res->save();
    return $res->toArray();
  }


  /**
   * 判断用户是否违规
   * @param $user_id
   * @param $node activity  活动违规（手动违规） reservation 预约违规（手动+自动）contest 大赛违规（手动违规） scenic 景点打卡（手动违规）  对应字段值 competite 征集活动违规（手动违规）
   */
  public function checkIsViolate($user_id, $node)
  {
    $number = $this->getViolateNumberOrUserId($user_id, $node);
    if (empty($number)) {
      return false; //未违规
    }
    $violate_config_data = ViolateConfig::where('id', 1)->first();
    if (empty($violate_config_data) || empty($violate_config_data[$node])) {
      return false; //不设置违规操作
    }
    if ($number >= $violate_config_data[$node]) {
      return true; //已违规
    }
    return false; //未违规
  }

  /**
   * 获取当前违规次数
   * @param $user_id
   * @param $node activity  活动违规（手动违规） reservation 预约违规（手动+自动）contest 大赛违规（手动违规） scenic 景点打卡（手动违规）  对应字段值 competite 征集活动违规（手动违规）
   * @param $way 获取数据方式  1 数量  2违规id
   */
  public function getViolateNumberOrUserId($user_id, $node, $way = 1)
  {
    $violate_config_data = $this->getViolateData($node);
    if ($violate_config_data === 0) {
      return 0; //配置文件未配置此违规项，则不记录违规
    }
    $violate_time = null;
    if (!empty($violate_config_data)) {
      $violate_time = $violate_config_data[$node . '_clear_day'];
    }
    //获取最近一次一键清空违规时间
    $node_violate_clear_time = UserViolate::where('user_id', $user_id)->value($node . '_violate_clear_time');
    $model = $this->getViolateDataModel($node);
    $ids = $model->where('is_violate', '<>', 1)->where(function ($query) use ($violate_time, $node_violate_clear_time) {
      if ($violate_time) {
        $query->where('violate_time', '>', date('Y-m-d H:i:s', strtotime("-$violate_time day")));
      }
      if ($node_violate_clear_time) {
        $query->where('violate_time', '>', $node_violate_clear_time);
      }
    })->where('user_id', $user_id)
      ->pluck('id');

    return $way == 1 ? count($ids) : $ids;
  }

  /**
   * 判断规则
   * @param $node activity  活动违规（手动违规） reservation 预约违规（手动+自动）contest 大赛违规（手动违规） 
   *        scenic 景点打卡（手动违规）  对应字段值  study_room_reservation 空间预约  competite 征集活动违规（手动违规）
   */
  public function getViolateData($node)
  {
    $violate_config = config("other.violate_config");
    if (empty($violate_config)) {
      return 0; //不设置违规操作
    }
    $violate_config_field = array_column($violate_config, 'field');
    if (!in_array($node, $violate_config_field)) {
      return 0; //不设置违规操作
    }
    $violate_config_data = ViolateConfig::where('id', 1)->first();
    //* / if (empty($violate_config_data) || empty($violate_config_data[$node])) {
    //   return 0; //不设置违规操作
    // } */
    return $violate_config_data;
  }


  /**
   * 获取违规数据
   * @param $user_id
   * @param $node activity  活动违规（手动违规） reservation 预约违规（手动+自动）contest 大赛违规（手动违规） scenic 景点打卡（手动违规）  对应字段值 study_room_reservation 空间预约
   */
  public function getUserViolateList($user_id, $node, $limit)
  {
    $user_violate_id = $this->getViolateNumberOrUserId($user_id, $node, 2);
    if (empty($user_violate_id)) {
      return [];
    }
    $model = $this->getViolateDataModel($node);
    $name_model = $this->getViolateNameModel($node);
    list($data_id, $data_name) = $this->getViolateDataIdAndName($node);
    $res = $model->select('id', $data_id, 'is_violate', 'violate_reason', 'violate_time')
      ->whereIn('id', $user_violate_id)
      ->orderByDesc('id')
      ->paginate($limit)
      ->toArray();
    foreach ($res['data'] as $key => $val) {
      $res['data'][$key]['name'] = $name_model->where('id', $val[$data_id])->value($data_name);
    }

    return $res;
  }
  /**
   * 获取对应对象
   * @param $node 
   */
  public function getViolateDataModel($node)
  {
    switch ($node) {
      case 'activity':
        return new ActivityApply();
        break;
      case 'reservation':
        return new ReservationApply(); //name
        break;
      case 'contest':
        return new ContestActivityWorks();
        break;
      case 'scenic':
        return new ScenicWorks();
        break;
      case 'study_room_reservation':
        return new StudyRoomReservationApply(); //name
        break;
      case 'competite':
        return new CompetiteActivityWorks();
        break;
      default:
        return null;
    }
  }
  /**
   * 获取对应对象
   * @param $node 
   */
  public function getViolateNameModel($node)
  {
    switch ($node) {
      case 'activity':
        return new Activity();
        break;
      case 'reservation':
        return new Reservation(); //name
        break;
      case 'contest':
        return new ContestActivity();
        break;
      case 'scenic':
        return new Scenic();
        break;
      case 'study_room_reservation':
        return new StudyRoomReservation(); //name
        break;
      case 'competite':
        return new CompetiteActivity();
        break;
      default:
        return null;
    }
  }
  /**
   * 获取对应对象
   * @param $node 
   */
  public function getViolateDataIdAndName($node)
  {
    switch ($node) {
      case 'activity':
        return ['act_id', 'title'];
        break;
      case 'reservation':
        return  ['reservation_id', 'name']; //name
        break;
      case 'contest':
        return  ['con_id', 'title'];
        break;
      case 'scenic':
        return  ['scenic_id', 'title'];
        break;
      case 'study_room_reservation':
        return  ['reservation_id', 'name']; //name
        break;
      case 'competite':
        return  ['con_id', 'title'];
        break;
      default:
        return null;
    }
  }
}
